package com.woniu.secondhand.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.common.constant.RedisKeyConstant;
import com.woniu.common.entity.ResultCode;
import com.woniu.common.exception.LifeException;
import com.woniu.common.utils.IdWorker;
import com.woniu.pay.entity.PayInfo;
import com.woniu.pay.entity.RefundInfo;
import com.woniu.pay.feign.PayFeignClient;
import com.woniu.secondhand.config.OrderQueueConfig;
import com.woniu.secondhand.constant.SecondhandMessageConstant;
import com.woniu.secondhand.constant.SecondhandOrderConstant;
import com.woniu.secondhand.constant.SecondhandProductConstant;
import com.woniu.secondhand.entity.dto.AfterOrderUpdateDTO;
import com.woniu.secondhand.entity.dto.BeforeOrderUpdateDTO;
import com.woniu.secondhand.entity.dto.MessageAddDTO;
import com.woniu.secondhand.mapper.SecondhandOrderMapper;
import com.woniu.secondhand.pojo.SecondhandOrder;
import com.woniu.secondhand.pojo.SecondhandProduct;
import com.woniu.secondhand.service.ISecondhandMessageService;
import com.woniu.secondhand.service.ISecondhandOrderService;
import com.woniu.secondhand.service.ISecondhandProductService;
import com.woniu.user.feignClient.AddressFeignClient;
import com.woniu.user.feignClient.UserFeignClient;
import com.woniu.user.pojo.Address;
import com.woniu.user.vo.UserLoginVO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author HMMT
 * @since 2023-05-20
 */
@Service
@Slf4j
public class SecondhandOrderServiceImpl extends ServiceImpl<SecondhandOrderMapper, SecondhandOrder> implements ISecondhandOrderService {
    @Autowired
    private ISecondhandOrderService orderService;
    @Autowired
    private ISecondhandProductService productService;
    @Autowired
    private ISecondhandMessageService messageService;
    @Autowired
    private SecondhandOrderMapper orderMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private PayFeignClient payFeignClient;
    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private AddressFeignClient addressFeignClient;

    @Override
    public SecondhandOrder createOrder(Integer productId, Integer addressId, UserLoginVO userLoginVO) {
        SecondhandProduct product = productService.getById(productId);
        if (product == null) {
            throw new LifeException(ResultCode.PRODUCT_NOT_EXIST.getMessage(), ResultCode.PRODUCT_NOT_EXIST);
        }
        if (Objects.equals(product.getDeleteStatus(), SecondhandProductConstant.DELETED)) {
            throw new LifeException(ResultCode.PRODUCT_NOT_DELETE.getMessage(), ResultCode.PRODUCT_NOT_DELETE);

        }
        if (Objects.equals(product.getVerifyStatus(), SecondhandProductConstant.UNVERIFIED)) {
            throw new LifeException(ResultCode.PRODUCT_NOT_VERIFY.getMessage(), ResultCode.PRODUCT_NOT_VERIFY);
        }
        Address address = addressFeignClient.getById(addressId).getData();
        SecondhandOrder order = new SecondhandOrder();
        IdWorker idWorker = new IdWorker();
        long nextId = idWorker.nextId();
        order.setOrderNo(nextId + "");
        order.setProductId(productId);
        order.setConsumerId(userLoginVO.getId());
        order.setProducerId(product.getProducerId());
        order.setStatus(SecondhandOrderConstant.PENDING_PAYMENT);
        order.setTotalAmount(product.getPrice());
        order.setPayAmount(product.getPrice());
        order.setPayType(SecondhandOrderConstant.UNPAID);
        order.setSourceType(SecondhandOrderConstant.PC_PAY);
        order.setAutoConfirmDay(SecondhandOrderConstant.AUTO_CONFIRM_DAY);
        order.setConfirmStatus(SecondhandOrderConstant.UN_CONFIRM);
        order.setDeleteStatus(SecondhandOrderConstant.UN_DELETED);
        order.setReceiverName(address.getName());
        order.setReceiverPhone(address.getMobile());
        order.setReceiverProvince(address.getProvince());
        order.setReceiverCity(address.getCity());
        order.setReceiverRegion(address.getCounty());
        order.setReceiverDetailAddress(address.getDetail());
        orderMapper.insert(order);
        product.setBuyStatus(SecondhandProductConstant.SOLD);
        productService.updateById(product);
        MessageAddDTO messageAddDTO = new MessageAddDTO();
        messageAddDTO.setOrderId(order.getId());
        messageAddDTO.setMessageType(SecondhandMessageConstant.BUY_SUCCESS_UNPAID_MESSAGE);
        messageService.addMessage(messageAddDTO, userLoginVO);
        rabbitTemplate.convertAndSend(OrderQueueConfig.ORDER_EXCHANGE, OrderQueueConfig.ROUTING_KEY, order.getOrderNo());
        return order;
    }

    @RabbitListener(queues = OrderQueueConfig.DLQ_ORDER_QUEUE)
    public void checkOrderTimeout(String orderNo) {
        log.debug("进入了死信队列 队列的订单id是{}", orderNo);
        //1.根据id查询订单在本地的状态
        SecondhandOrder order = getByOrderNo(orderNo);
        //2.如果本地订单状态不是待支付 不做处理
        if (!Objects.equals(order.getStatus(), SecondhandOrderConstant.PENDING_PAYMENT)) {
            log.debug("订单编号为{}的订单已经处理了", orderNo);
        }
        //3.如果是待支付 查询第三方状态 第三方未支付 超时 修改订单状态
/*        Object status = payFeignClient.queryStatusByOutTradeNo(orderNo).getData();
        if ("WAIT_BUYER_PAY".equals(status) || "TRADE_CLOSED".equals(status)) {
        }*/
        order.setStatus(SecondhandOrderConstant.CLOSED_ORDER);
        orderService.updateById(order);
        log.debug("订单已经超时");
    }


    @Override
    public SecondhandOrder getByProductIdAndStatusEqualsReceiveSuccess(Integer productId) {
        QueryWrapper<SecondhandOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("product_id", productId);
        wrapper.eq("status", SecondhandOrderConstant.RECEIVE_SUCCESS);
        SecondhandOrder order = orderService.getOne(wrapper);
        return order;
    }

    @Override
    public SecondhandOrder getByOrderNo(String orderNo) {
        QueryWrapper<SecondhandOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no", orderNo);
        SecondhandOrder order = orderMapper.selectOne(wrapper);
        return order;
    }

    @SneakyThrows
    @Override
    public void pay(SecondhandOrder order) {
        Byte status = order.getStatus();
        if (!Objects.equals(status, SecondhandOrderConstant.PENDING_PAYMENT)) {
            throw new LifeException(ResultCode.DATA_IS_WRONG.getMessage(), ResultCode.DATA_IS_WRONG);
        }
        PayInfo payInfo = new PayInfo();
        payInfo.setOutTradeNo(order.getOrderNo());
        payInfo.setTotalAmount(order.getTotalAmount());
        SecondhandProduct product = productService.getById(order.getProductId());
        payInfo.setSubject(product.getTitle());
        payInfo.setReturnUrl(SecondhandOrderConstant.RETURN_URL);
        payInfo.setNotifyUrl(SecondhandOrderConstant.NOTIFY_URL);
        String form = (String) payFeignClient.pay(payInfo).getData();
        log.debug(form);
        log.debug(order.getOrderNo());
    }

    @Override
    public SecondhandOrder updateOrderBeforePay(BeforeOrderUpdateDTO orderUpdateDTO) {
        SecondhandOrder order = orderMapper.selectById(orderUpdateDTO.getId());
        if (orderUpdateDTO.getTotalAmount() != null) {
            order.setTotalAmount(orderUpdateDTO.getTotalAmount());
        }
        if (orderUpdateDTO.getPayAmount() != null) {
            order.setPayAmount(orderUpdateDTO.getPayAmount());
        }
        if (orderUpdateDTO.getFreightAmount() != null) {
            order.setFreightAmount(orderUpdateDTO.getFreightAmount());
        }
        if (orderUpdateDTO.getNote() != null) {
            order.setNote(orderUpdateDTO.getNote());
        }
        orderService.updateById(order);
        return order;
    }

    @Override
    public SecondhandOrder updateOrderAfterPay(AfterOrderUpdateDTO orderUpdateDTO, UserLoginVO userLoginVO) {
        SecondhandOrder order = orderMapper.selectById(orderUpdateDTO.getId());
        if (orderUpdateDTO.getDeliveryCompany() != null) {
            order.setDeliveryCompany(orderUpdateDTO.getDeliveryCompany());
        }
        if (orderUpdateDTO.getDeliverySn() != null) {
            order.setDeliverySn(orderUpdateDTO.getDeliverySn());
        }
        if (orderUpdateDTO.getReceiverName() != null) {
            order.setReceiverName(orderUpdateDTO.getReceiverName());
        }
        if (orderUpdateDTO.getReceiverPhone() != null) {
            order.setReceiverPhone(orderUpdateDTO.getReceiverPhone());
        }
        if (orderUpdateDTO.getReceiverProvince() != null) {
            order.setReceiverProvince(orderUpdateDTO.getReceiverProvince());
        }
        if (orderUpdateDTO.getReceiverCity() != null) {
            order.setReceiverCity(orderUpdateDTO.getReceiverCity());
        }
        if (orderUpdateDTO.getReceiverRegion() != null) {
            order.setReceiverRegion(orderUpdateDTO.getReceiverRegion());
        }
        if (orderUpdateDTO.getReceiverDetailAddress() != null) {
            order.setReceiverDetailAddress(orderUpdateDTO.getReceiverDetailAddress());
        }
        order.setStatus(SecondhandOrderConstant.DELIVER_SUCCESS);
        order.setDeliveryTime(new Date());
        orderService.updateById(order);
        MessageAddDTO messageAddDTO = new MessageAddDTO();
        messageAddDTO.setOrderId(order.getId());
        messageAddDTO.setMessageType(SecondhandMessageConstant.DELIVER_SUCCESS_MESSAGE);
        messageService.addMessage(messageAddDTO, userLoginVO);
        rabbitTemplate.convertAndSend(OrderQueueConfig.ORDER_EXCHANGE1, OrderQueueConfig.ROUTING_KEY1, order.getOrderNo());
        return order;
    }

    @RabbitListener(queues = OrderQueueConfig.DLQ_ORDER_QUEUE1)
    public void checkOrderTimeout1(String orderNo) {
        log.debug("进入了死信队列 队列的订单id是{}", orderNo);
        //1.根据id查询订单在本地的状态
        SecondhandOrder order = getByOrderNo(orderNo);
        //2.如果本地订单状态不是待支付 不做处理
        if (!Objects.equals(order.getStatus(), SecondhandOrderConstant.DELIVER_SUCCESS)) {
            log.debug("订单编号为{}的订单已经处理了", orderNo);
        }
        //3.如果是待支付 查询第三方状态 第三方未支付 超时 修改订单状态
/*        Object status = payFeignClient.queryStatusByOutTradeNo(orderNo).getData();
        if ("WAIT_BUYER_PAY".equals(status) || "TRADE_CLOSED".equals(status)) {
        }*/
        order.setStatus(SecondhandOrderConstant.RECEIVE_SUCCESS);
        order.setReceiveTime(new Date());
        orderService.updateById(order);
        log.debug("订单已经超时");
    }

    @Override
    public void closeOrder(Integer orderId, UserLoginVO userLoginVO) {
        SecondhandOrder order = orderService.getById(orderId);
        if (!Objects.equals(userLoginVO.getId(), order.getProducerId()) && !Objects.equals(userLoginVO.getId(), order.getConsumerId())) {
            throw new LifeException(ResultCode.PERMISSION_NO_ACCESS.getMessage(), ResultCode.PERMISSION_NO_ACCESS);
        }
        order.setStatus(SecondhandOrderConstant.CLOSED_ORDER);
        orderService.updateById(order);
        productService.updateToUnsold(order.getProductId());
    }

    @Override
    public SecondhandOrder updateOrderConfirm(UserLoginVO userLoginVO, Integer orderId) {
        SecondhandOrder order = orderMapper.selectById(orderId);
        order.setStatus(SecondhandOrderConstant.RECEIVE_SUCCESS);
        order.setReceiveTime(new Date());
        orderService.updateById(order);
        return order;
    }

    @Override
    public SecondhandOrder updateOrderRefund(UserLoginVO userLoginVO, Integer orderId) {
        SecondhandOrder order = orderMapper.selectById(orderId);
        Byte status = order.getStatus();
        if (!status.equals(SecondhandOrderConstant.RECEIVE_SUCCESS) &&
                !status.equals(SecondhandOrderConstant.COMMENT_SUCCESS)) {
            throw new LifeException(ResultCode.NON_REFUNDABLE.getMessage(), ResultCode.NON_REFUNDABLE);
        }
        Date deliveryTime = order.getReceiveTime();
        Calendar calendar = Calendar.getInstance();
        // 设置时间
        calendar.setTime(deliveryTime);
        // 将时间调整到7天后
        calendar.add(Calendar.DAY_OF_MONTH, 7);
        // 获取时间
        Date afterTime = calendar.getTime();
        Date now = new Date();
        if (afterTime.getTime() < now.getTime()) {
            throw new LifeException(ResultCode.NON_REFUNDABLE.getMessage(), ResultCode.NON_REFUNDABLE);
        }
        RefundInfo refundInfo = new RefundInfo();
        refundInfo.setOutTradeNo(order.getOrderNo());
        refundInfo.setRefundAmount(order.getTotalAmount());
        payFeignClient.refund(refundInfo);
        order.setStatus(SecondhandOrderConstant.INVALID_ORDER);
        orderService.updateById(order);
        return order;
    }
}
